package com.youlu.campus.service.pay.impl;

import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.entity.ActivityInfo;
import com.youlu.campus.entity.CaGroupInfo;
import com.youlu.campus.entity.PayCategoryConfig;
import com.youlu.campus.entity.VO.req.PayCategoryConfigQueryVO;
import com.youlu.campus.service.pay.PayCategoryConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

@Slf4j
@Service
public class PayCategoryConfigServiceImpl implements PayCategoryConfigService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public Page<PayCategoryConfig> list(PayCategoryConfigQueryVO req) {
        Query query = new Query();
        if (StringUtils.isNotBlank(req.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        }
        if (StringUtils.isNotBlank(req.getName())) {
            Pattern compile = Pattern.compile("^.*" + req.getName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").is(compile));
        }
        if (Objects.nonNull(req.getPublished())) {
            query.addCriteria(Criteria.where("published").is(req.getPublished()));
        }
        query.addCriteria(Criteria.where("deleted").ne(true));
        long count = mongoTemplate.count(query, PayCategoryConfig.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<PayCategoryConfig> infos = mongoTemplate.find(query.with(pageRequest), PayCategoryConfig.class);
        for (PayCategoryConfig payCategoryConfig : infos) {
            Query query1 = new Query().addCriteria(Criteria.where("id").is(payCategoryConfig.getId()));
            CaGroupInfo caGroupInfo = mongoTemplate.findOne(query1, CaGroupInfo.class);
            if (Objects.nonNull(caGroupInfo)) {
                payCategoryConfig.setCaGroupName(caGroupInfo.getName());
            }
            if (StringUtils.isNotBlank(payCategoryConfig.getActivityId())) {
                ActivityInfo activityInfo = this.mongoTemplate.findById(payCategoryConfig.getActivityId(),
                        ActivityInfo.class);
                if (Objects.nonNull(activityInfo)) {
                    payCategoryConfig.setActivityName(activityInfo.getName());
                }
            }
        }
        return PageableExecutionUtils.getPage(infos, pageRequest, () -> count);
    }

    @Override
    public PayCategoryConfig create(PayCategoryConfig req) {
        req.setId(null);
        if (Objects.isNull(req.getCreatedTime())) {
            req.setCreatedTime(new Date());
        }
        return mongoTemplate.insert(req);
    }

    @Override
    public boolean update(PayCategoryConfig req) {
        req.setUpdatedTime(new Date());
        mongoTemplate.save(req);
        return true;
    }

    @Override
    public boolean delete(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("deleted", true);
        update.set("updatedTime", new Date());
        UpdateResult result = mongoTemplate.updateFirst(query, update, PayCategoryConfig.class);
        return result.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public PayCategoryConfig findOne(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, PayCategoryConfig.class);
    }

    @Override
    public PayCategoryConfig findByType(String type, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("type").is(type).and("activityId").is(activityId));
        Sort sort = Sort.by(Sort.Direction.DESC, "priority");
        query.with(sort);
        return mongoTemplate.findOne(query, PayCategoryConfig.class);
    }

    @Override
    public List<PayCategoryConfig> findByActivityId(String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").is(activityId));
        query.addCriteria(Criteria.where("deleted").ne(Boolean.TRUE));
        Sort sort = Sort.by(Sort.Direction.DESC, "priority");
        query.with(sort);
        return mongoTemplate.find(query, PayCategoryConfig.class);
    }

    @Override
    public PayCategoryConfig findByCategoryId(String categoryId, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(categoryId).and("activityId").is(activityId));
        Sort sort = Sort.by(Sort.Direction.DESC, "priority");
        query.with(sort);
        return mongoTemplate.findOne(query, PayCategoryConfig.class);
    }

    @Override
    public List<PayCategoryConfig> findByCaGroupId(String caGroupId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("caGroupId").is(caGroupId));
        Sort sort = Sort.by(Sort.Direction.DESC, "priority");
        query.with(sort);
        return mongoTemplate.find(query, PayCategoryConfig.class);
    }
}
